package io.jenkins.plugins.feiqiu;

import java.io.PrintStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by pigercc on 2016/6/17.
 */
public class FeiqUtil {

  private final static String DEFAULT_BROADCASE_IP = "226.81.9.8";
  private final static int DEFAULT_BROADCASE_PORT = 2425;
  private final static String DEFAULT_FONT = "{/font;-16 0 0 0 400 0 0 0 134 0 0 2 32 微软雅黑 8404992;}";
  private final static String DEFAULT_ENCODING = "GBK";

  private final static long MSG_TYPE_GROUP = 4194339L;

  private final static int IP_MSG_PORT = 2425;

  public static void sendPersonMsg(String msg, String userName, String pcName,
      FeiqiuTarget target) throws Exception {
    String ip = target.getIp();
    if (Objects.isNull(ip) || ip.isEmpty()) {
      return;
    }
    Integer port = target.getPort();
    if (Objects.isNull(port) || port == 0) {
      port = IP_MSG_PORT;
    }
    InetAddress group = InetAddress.getByName(ip);

    byte[] sendData = String.format("1:%d:%s:%s:32:%s", (System.currentTimeMillis() / 1000),
        userName, pcName, msg).getBytes(DEFAULT_ENCODING);
    DatagramPacket dp = new DatagramPacket(sendData, sendData.length,
        InetAddress.getByName(ip),
        port);
    DatagramSocket ds = new DatagramSocket();
    ds.send(dp);
    ds.close();
  }

  public static void sendGroupMsg(long groupNum, String msg, String userName, String pcName,
      String mac, SendRangeOpt opt, PrintStream logger) {
    long sleep = 1000 / opt.speed;
    for (int i = opt.start; i <= opt.end; i++) {
      String ip = opt.ipRange + "." + i;
      logger.printf("send to %s\n", ip);
      try {
        InetAddress group = InetAddress.getByName(ip);
        byte[] sendData = getSendData(groupNum, msg, userName, pcName, mac);
        DatagramPacket dp = new DatagramPacket(sendData, sendData.length, group,
            DEFAULT_BROADCASE_PORT);
        try (DatagramSocket sock = new DatagramSocket()) {
          sock.send(dp);
        }
        Thread.sleep(sleep);
      } catch (Exception e) {
        e.printStackTrace(logger);
      }

    }
  }

  /**
   * 向指定群，发送群消息
   */
  public static void sendGroupMsg(String msg, String userName, String pcName,
      String mac, FeiqiuTarget target) throws Exception {
    String ip = target.getIp();
    if (Objects.isNull(ip) || ip.isEmpty()) {
      ip = DEFAULT_BROADCASE_IP;
    }
    Integer port = target.getPort();
    if (Objects.isNull(port) || port == 0) {
      port = DEFAULT_BROADCASE_PORT;
    }
    InetAddress group = InetAddress.getByName(ip);
    MulticastSocket msr = new MulticastSocket(port);
    msr.joinGroup(group);
    byte[] sendData = getSendData(target.getGroupId(), msg, userName, pcName, mac);
    DatagramPacket dp = new DatagramPacket(sendData, sendData.length, group,
        DEFAULT_BROADCASE_PORT);
    msr.send(dp);
    msr.close();
  }

  private static byte[] getSendData(long groupNum, String msg, String userName, String pcName,
      String mac) throws Exception {
    byte[] groupData = String.format("QUNMSGMARK#%s_%d#%s%s", Long.toHexString(groupNum),
        (System.currentTimeMillis() / 1000), msg, DEFAULT_FONT).getBytes(DEFAULT_ENCODING);
    byte[] groupEncryptData = encrypt(mac, groupData);
    byte[] headData = String.format("1_lbt4_0#128#%s#0#0#%d#4000#9:%d:%s:%s:%d:", mac,
        groupEncryptData.length, (System.currentTimeMillis() / 1000), pcName, userName,
        MSG_TYPE_GROUP).getBytes(DEFAULT_ENCODING);

    byte[] fullData = new byte[headData.length + groupEncryptData.length];
    System.arraycopy(headData, 0, fullData, 0, headData.length);
    System.arraycopy(groupEncryptData, 0, fullData, headData.length, groupEncryptData.length);
    return fullData;
  }

  //Blowfish加密
  private static byte[] encrypt(String keyValue, byte[] encryptData) throws Exception {
    SecretKeySpec key = new SecretKeySpec(keyValue.getBytes(), "Blowfish");
    IvParameterSpec iv = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0});
    Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    return cipher.doFinal(encryptData);
  }

  public static class SendRangeOpt {

    public String ipRange;
    public Integer start;
    public Integer end;
    public Long speed;
  }


}
